package plp.expressions2.expression;

import plp.expressions1.util.Tipo;
import plp.expressions2.memory.AmbienteCompilacao;
import plp.expressions2.memory.AmbienteExecucao;
import plp.expressions2.memory.VariavelNaoDeclaradaException;
import plp.expressions2.util.LinguagemVisitor;
import plp.expressions2.util.VisitorException;

public class Id extends Expressao {

	private String idName;

	public Id(String strName) {
		idName = strName;
	}
	
	public Id(String strName, int line, int beginColumn,
			int endColumn) {
		this(strName);
		this.line = line;
		this.beginColumn = beginColumn;
		this.endColumn = endColumn;
	}

	@Override
	public String toString() {
		return idName;
	}

	public Valor avaliar(AmbienteExecucao ambiente) throws VariavelNaoDeclaradaException {
		return ambiente.get(this);
	}


	/**
	 * Realiza a verificacao de tipos desta expressao. Ser&aacute; v&aacute;lida
	 * se o identificador estiver declarado.
	 * 
	 * @param amb
	 *            o ambiente de compila��o.
	 * @return <code>true</code> se os tipos da expressao sao validos;
	 *         <code>false</code> caso contrario.
	 * @exception VariavelNaoDeclaradaException
	 *                se este identificador nao estiver no ambiente.
	 * @throws VisitorException 
	 */
	public boolean checaTipo(AmbienteCompilacao amb)
			throws VariavelNaoDeclaradaException, VisitorException {
		boolean result = true;
		try {
			amb.get(this); // se estiver no ambiente, entao esta ok.
		} catch (VariavelNaoDeclaradaException exc) {
			accept(visit, amb);
			throw exc;
		} 
		return result;
	}

	/**
	 * Retorna os tipos possiveis desta expressao.
	 * 
	 * @param amb
	 *            o ambiente de compila��o.
	 * @return os tipos possiveis desta expressao.
	 * @exception VariavelNaoDeclaradaException
	 *                se este identificador nao estiver no ambiente.
	 */
	public Tipo getTipo(AmbienteCompilacao amb)
			throws VariavelNaoDeclaradaException {
		return amb.get(this);
	}

	public String getIdName() {
		return idName;
	}

	public void setIdName(String idName) {
		this.idName = idName;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + (idName == null ? 0 : idName.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (!obj.getClass().isAssignableFrom(getClass())) {
			return false;
		}
		boolean r;

		Id other = (Id) obj;
		if (this.idName == null) {
			r = other.idName == null;
		} else {
			r = this.idName.equals(other.idName);
		}

		return r;
	}

	@Override
	public void accept(LinguagemVisitor lingVisitor, AmbienteCompilacao ambiente) throws VisitorException {
		lingVisitor.visit(this,ambiente);
	}
}
